package com.tssup.fesco.service.impl;

import com.tssup.fesco.common.constants.GoodsConstants;
import com.tssup.fesco.common.enumeration.OperateStockType;
import com.tssup.fesco.common.enums.LogType;
import com.tssup.fesco.common.exeception.LockAcquisitionException;
import com.tssup.fesco.common.exeception.LockReleaseException;
import com.tssup.fesco.common.exeception.RetException;
import com.tssup.fesco.common.lock.Lock;
import com.tssup.fesco.ofc.vo.AddStockParamVo;
import com.tssup.fesco.sales.goods.persistent.mapper.IRealStockHistoryMapper;
import com.tssup.fesco.sales.goods.persistent.mapper.RRealStockMapper;
import com.tssup.fesco.sales.goods.persistent.pojo.IRealStockHistory;
import com.tssup.fesco.sales.goods.persistent.pojo.RRealStock;
import com.tssup.fesco.service.StockService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * Created by franco.cheng on 2017/3/31.
 */
@Service
public class StockServiceImpl implements StockService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RRealStockMapper realStockMapper;

    @Autowired
    private IRealStockHistoryMapper realStockHistoryMapper;

    @Autowired
    private Lock lock;

    @Override
    @Transactional
    public void addStock(AddStockParamVo addStockParamVo) {
        if (addStockParamVo != null && CollectionUtils.isNotEmpty(addStockParamVo.getSkus())
                && (StringUtils.isNotEmpty(addStockParamVo.getOrderCode()) || StringUtils.isNotEmpty(addStockParamVo.getOfcOrderCode()))){
            for (AddStockParamVo.GoodsNumVo goodsVo : addStockParamVo.getSkus()){
                operateStock(goodsVo.getSkuId(), goodsVo.getNum(), OperateStockType.ADD, addStockParamVo.getOrderCode(), addStockParamVo.getOfcOrderCode());
            }
        }
    }

    private void operateStock(Integer skuId, Integer num, OperateStockType operateStockType, String orderCode, String ofcOrderCode){
        try {
            if (lock.lock(skuId.toString(), 600, TimeUnit.SECONDS)){
                RRealStock rRealStock = realStockMapper.selectBySkuId(skuId);
                Integer originalStock = rRealStock.getStock();
                if (OperateStockType.ADD.equals(operateStockType)){
                    rRealStock.setStock(rRealStock.getStock() + num);
                    realStockMapper.updateByPrimaryKey(rRealStock);
                } else {
                    if ( rRealStock.getStock() < num ){
                        lock.unlock(skuId.toString());
                        throw new RetException(GoodsConstants.UNDERSTOCK_CODE, GoodsConstants.UNDERSTOCK_MSG);
                    }
                    rRealStock.setStock(rRealStock.getStock() - num);
                    realStockMapper.updateByPrimaryKey(rRealStock);
                    IRealStockHistory iRealStockHistory = new IRealStockHistory();
                    iRealStockHistory.setOriginalStock(originalStock);
                    iRealStockHistory.setStock(rRealStock.getStock());
                    iRealStockHistory.setSkuId(skuId);
                    iRealStockHistory.setLogDate(new Date());
                    iRealStockHistory.setStockId(rRealStock.getStockId());
                    iRealStockHistory.setLogType(LogType.MODIFIED.getValue());
                    iRealStockHistory.setLogMemo(operateStockType.getDisplayName());
                    iRealStockHistory.setOrderCode(orderCode);
                    iRealStockHistory.setOfcOrderCode(ofcOrderCode);
                    realStockHistoryMapper.insert(iRealStockHistory);
                }
                lock.unlock(skuId.toString());
            } else {
                Thread.sleep(200);
                operateStock(skuId, num, operateStockType, orderCode, ofcOrderCode);
            }
        } catch (LockAcquisitionException | LockReleaseException | InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
    }
}
